import * as obvm from '../../runtime/vm.mjs'
import * as THREE from 'three';
import { ArcballControls } from 'three/addons/controls/ArcballControls.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

class Threejs {
    /**
     * @type {THREE.Renderer}
     */
    renderer;
    /**
     * @type {THREE.Scene}
     */
    scene;
    /**
     * @type {THREE.Camera}
     */
    camera;

    controls;
    constructor(config) {
        Object.assign(this, config);
        if (!this.prompt) {
            this.prompt = window.prompt.bind(window);
        }
    }
    install(script) {
        script.InstallLib("three.js", "three.js", [
            script.NativeUtil.objFieldGetter('position', 'NObjectRegister'),
            script.NativeUtil.closureVoid((v, d) => {
                v.setX(d);
            }, ['NObjectRegister', 'DoubleRegister']),
            script.NativeUtil.closureVoid((v, d) => {
                v.setY(d);
            }, ['NObjectRegister', 'DoubleRegister']),
            script.NativeUtil.closureVoid((v, d) => {
                v.setZ(d);
            }, ['NObjectRegister', 'DoubleRegister']),
            
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.BoxGeometry();
            }, 'NObjectRegister', [], false),
            
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.CircleGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.ConeGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.CylinderGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.DodecahedronGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.EdgesGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.ExtrudeGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.IcosahedronGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.LatheGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.OctahedronGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.PlaneGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.PolyhedronGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.RingGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.ShapeGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.SphereGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.TetrahedronGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.TorusGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.TorusKnotGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.TubeGeometry();
            }, 'NObjectRegister', [], false),
            script.NativeUtil.closureReturnValue(() => {
                return new THREE.WireframeGeometry();
            }, 'NObjectRegister', [], false),


            script.NativeUtil.closureVoid((o) => {
                this.scene.add(o)
            }, ['NObjectRegister']),
            script.NativeUtil.closureReturnValue((geometry, material) => {
                return new THREE.Mesh(geometry, material);
            }, 'NObjectRegister', ['NObjectRegister', 'NObjectRegister'], false),
            script.NativeUtil.closureReturnValue((color) => {
                color = color >> 8 & 0xffffff;
                return new THREE.MeshStandardMaterial({ color });
            }, 'NObjectRegister', ['LongRegister'], false),
            script.NativeUtil.closureReturnValue((color, x, y, z) => {
                color = color >> 8 & 0xffffff;
                let m = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshStandardMaterial({ color }));
                m.position.set(x, y, z);
                this.scene.add(m);
                return m;
            }, 'NObjectRegister', ['LongRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'], false),
            script.NativeUtil.closureVoid((mesh, color) => {
                color = color >> 8 & 0xffffff;
                mesh.material.color.set(color);
            }, ['NObjectRegister', 'LongRegister'], false),
            script.NativeUtil.closureVoid((mesh, x, y, z) => {
                mesh.scale.set(x, y, z);
            }, ['NObjectRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'], false),
            script.NativeUtil.closureReturnValue((color, v3) => {
                color = color >> 8 & 0xffffff;
                let m = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshStandardMaterial({ color }));
                m.position.copy(v3);
                this.scene.add(m);
                return m;
            }, 'NObjectRegister', ['LongRegister', 'NObjectRegister'], false),
            script.NativeUtil.objFieldGetter('x', 'DoubleRegister'),
            script.NativeUtil.objFieldGetter('y', 'DoubleRegister'),
            script.NativeUtil.objFieldGetter('z', 'DoubleRegister'),
            script.NativeUtil.closureVoid((mesh) => {
                this.scene.remove(mesh);
            }, ['NObjectRegister'], false),
            script.NativeUtil.closureVoid((mesh, opacity) => {
                mesh.material.opacity = opacity;
                mesh.material.transparent = true;
            }, ['NObjectRegister', 'DoubleRegister'], false),
            script.NativeUtil.closureReturnValue((mesh) => {
                return mesh.material.opacity;
            }, 'DoubleRegister', ['NObjectRegister'], false),
        ]);
    }
}
export { Threejs };